package com.inspectortime.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Map;

import com.inspectortime.domain.type.Time;

public class CalendarUtil {

	private static final String navDateFormat = "MM/dd/yyyy";
	private static Map<String, String> daysOfWeek = null; // TODO: PUT THIS IN A
															// SPRING CONFIG

	static {
		daysOfWeek = new LinkedHashMap<String, String>();
		daysOfWeek.put(Integer.toString(Calendar.SUNDAY), "Sunday");
		daysOfWeek.put(Integer.toString(Calendar.MONDAY), "Monday");
		daysOfWeek.put(Integer.toString(Calendar.TUESDAY), "Tuesday");
		daysOfWeek.put(Integer.toString(Calendar.WEDNESDAY), "Wednesday");
		daysOfWeek.put(Integer.toString(Calendar.THURSDAY), "Thursday");
		daysOfWeek.put(Integer.toString(Calendar.FRIDAY), "Friday");
		daysOfWeek.put(Integer.toString(Calendar.SATURDAY), "Saturday");
	}

	public static final Date formatNavDate(String dateStr)
			throws ParseException {
		return new SimpleDateFormat(navDateFormat).parse(dateStr);
	}

	public static final String convertToNavDateString(Date date) {
		return new SimpleDateFormat(navDateFormat).format(date);
	}

	/**
	 * Creates a Calendar with today's date, zeroing out everything smaller than
	 * the day (hours, minutes, etc)
	 * 
	 * @return today calendar
	 */
	public static Calendar createDayCalendar() {
		Calendar cal = new GregorianCalendar();
		removeTime(cal);
		return cal;
	}
	
	public static void removeDate(Calendar cal) {
		cal.set(Calendar.YEAR, 0);
		cal.set(Calendar.MONTH, 0);
		cal.set(Calendar.DATE, 0);
		removeTime(cal);
	}

	public static void removeTime(Calendar cal) {
		cal.set(Calendar.HOUR, 0);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
	}

	/**
	 * Sets the hour and removes all smaller values (min, sec, etc)
	 * 
	 * @param cal
	 */
	public static void setHour(Calendar cal, int hourOfDay) {
		removeTime(cal);
		cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
	}

	/**
	 * Creates a Calendar with year, month, day params, zeroing out everything
	 * smaller than the day (hours, minutes, etc)
	 * 
	 * @return calendar
	 */
	public static Calendar createDayCalendar(int year, int month, int day) {
		Calendar cal = new GregorianCalendar();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month);
		cal.set(Calendar.DAY_OF_MONTH, day);
		removeTime(cal);
		return cal;
	}

	public static String getDisplayableDayOfWeek(int day) {
		return daysOfWeek.get(Integer.toString(day));
	}

	public static Map<String, String> getDisplayableDaysOfWeekMap() {
		return daysOfWeek;
	}

	/**
	 * Return true if any of the dates within startDate and endDate are the same
	 * as any dates within compareStartDate and compareEndDate
	 * 
	 */
	public static boolean isOverlapping(Calendar startDate, Calendar endDate,
			Calendar compareStartDate, Calendar compareEndDate) {
		Date compareEnd = null;
		if (compareEndDate != null) {
			// See Day.canPopulateFrom for reason for this workaround
			compareEnd = compareEndDate.getTime();
		}
		return isOverlapping(startDate.getTime(), endDate.getTime(), compareStartDate.getTime(), compareEnd);
	}
	
	public static boolean isOverlapping(Time start, Time end, Time compareStart, Time compareEnd) {
		return isOverlapping(start.toDate(), end.toDate(), compareStart.toDate(), compareEnd.toDate());
	}
	
	/**
	 * Return true if any of the dates within startDate and endDate are the same
	 * as any dates within compareStartDate and compareEndDate
	 * 
	 */
	public static boolean isOverlapping(Date startDate, Date endDate,
			Date compareStartDate, Date compareEndDate) {
		long thisStartMillis = startDate.getTime();
		long thisEndMillis = endDate.getTime();
		long compareStartMillis = compareStartDate.getTime();

		if (compareStartMillis >= thisStartMillis
				&& compareStartMillis <= thisEndMillis) {
			return true;
		}

		if (compareEndDate != null) {
			long compareEndMillis = compareEndDate.getTime();
			if (compareEndMillis >= thisStartMillis
					&& compareEndMillis <= thisEndMillis) {
				return true;
			}
		}
		return false;
	}

}
